<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        
        
        
        <link rel="shortcut icon" href="../img/favicon.ico">

	<title>REST API - JavaBaas</title>

        <link href="../css/bootstrap-custom.min.css" rel="stylesheet">
        <link href="../css/font-awesome-4.0.3.css" rel="stylesheet">
        <link href="../css/base.css" rel="stylesheet">
        <link rel="stylesheet" href="../css/highlight.css">

        <!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
        <!--[if lt IE 9]>
            <script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
            <script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
        <![endif]-->

        
    </head>

    <body>

        <div class="navbar navbar-default navbar-fixed-top" role="navigation">
    <div class="container">

        <!-- Collapsed navigation -->
        <div class="navbar-header">
            
            <!-- Expander button -->
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            

            <!-- Main title -->
            <a class="navbar-brand" href="..">JavaBaas</a>
        </div>

        <!-- Expanded navigation -->
        <div class="navbar-collapse collapse">
            
                <!-- Main navigation -->
                <ul class="nav navbar-nav">
                
                
                    <li >
                        <a href="..">主页</a>
                    </li>
                
                
                
                    <li class="dropdown">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">功能概述 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                        
                            
<li >
    <a href="../overview/Object/">数据存储</a>
</li>

                        
                        </ul>
                    </li>
                
                
                
                    <li class="dropdown active">
                        <a href="#" class="dropdown-toggle" data-toggle="dropdown">用户手册 <b class="caret"></b></a>
                        <ul class="dropdown-menu">
                        
                            
<li >
    <a href="../commandline/">命令行工具</a>
</li>

                        
                            
<li class="active">
    <a href="./">REST API</a>
</li>

                        
                        </ul>
                    </li>
                
                
                
                    <li >
                        <a href="../download/">下载</a>
                    </li>
                
                
                </ul>
            

            <ul class="nav navbar-nav navbar-right">
                <li>
                    <a href="#" data-toggle="modal" data-target="#mkdocs_search_modal">
                        <i class="fa fa-search"></i> Search
                    </a>
                </li>
                
                    <li >
                        <a rel="next" href="../commandline/">
                            <i class="fa fa-arrow-left"></i> Previous
                        </a>
                    </li>
                    <li >
                        <a rel="prev" href="../download/">
                            Next <i class="fa fa-arrow-right"></i>
                        </a>
                    </li>
                
                
            </ul>
        </div>
    </div>
</div>

        <div class="container">
            
                <div class="col-md-3"><div class="bs-sidebar hidden-print affix well" role="complementary">
    <ul class="nav bs-sidenav">
    
        <li class="main active"><a href="#rest-api">REST API</a></li>
        
            <li><a href="#_1">安全机制</a></li>
        
            <li><a href="#_4">响应格式</a></li>
        
            <li><a href="#_5">接口概览</a></li>
        
            <li><a href="#_12">用户</a></li>
        
    
    </ul>
</div></div>
                <div class="col-md-9" role="main">

<h1 id="rest-api">REST API</h1>
<p>REST API 可以让你用任何支持发送 HTTP 请求的设备来与 JavaBaas 进行交互，你可以使用 REST API 做很多事情，比如：</p>
<ul>
<li>一个移动网站可以通过 JavaScript 来获取 JavaBaas 上的数据.</li>
<li>一个网站可以展示来自 JavaBaas 的数据。</li>
<li>你可以上传大量的数据，之后可以被一个移动 App 读取。</li>
<li>你可以下载最近的数据来进行你自定义的分析统计。</li>
<li>使用任何语言写的程序都可以操作 JavaBaas 上的数据。</li>
</ul>
<h2 id="_1">安全机制</h2>
<h3 id="_2">三级权限</h3>
<p>所有的API请求都是在安全的鉴权机制下进行的，接口分为三级权限。分别为<code>admin</code>（超级）权限、<code>master</code>（管理）权限、<code>user</code>（普通）权限。每个接口都有其调用所需要的对应权限。无权限或使用错误的权限将调用失败。</p>
<h4 id="admin">超级权限（admin）</h4>
<p><code>admin</code>权限为系统的超级权限，系统的核心管理接口需要使用此权限进行调用，如创建删除应用等。在<code>src/main/resources/application.properties</code>需要配置auth.admin.key，系统才能正常工作。如：</p>
<pre><code>auth.admin.key = V1hwT1UyRkhUblZpUjNoclVWTlZlbEpEVlhwU1FTVXpSQ1V6UkElM0QlM0Qc3Rhc
</code></pre>

<p>其中key由用户自由生成。</p>
<h4 id="master">管理权限（master）</h4>
<p><code>master</code>权限为管理权限。对应用中<code>类</code>的管理、<code>字段</code>的管理、部署<code>云代码</code>等，均需要使用此权限进行调用。因此使用此权限需要指定被操作appId。同时此权限也可以进行无视ACL权限（表级和对象级）的<code>对象</code>增删改查操作。</p>
<h4 id="user">普通权限（user）</h4>
<p><code>user</code>权限为普通权限。可以进行<code>对象</code>的增删改查操作。适合在客户端调用时使用。</p>
<h3 id="_3">接口调用鉴权方式</h3>
<p>在所有的API请求头部（header）中，为了检查请求者的有效身份，需要添加以下信息：</p>
<table>
<thead>
<tr>
<th>名称</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>JB-Timestamp</td>
<td>客户端产生本次请求的 unix 时间戳，精确到毫秒。</td>
</tr>
<tr>
<td>JB-AppId</td>
<td>调用应用的AppId，用以表示正在操作哪一个应用。（当使用管理授权或普通授权时需要）</td>
</tr>
<tr>
<td>JB-AdminSign（三选一）</td>
<td>将adminKey加上":"再加上timestamp组成的字符串，再对它做 MD5 签名后的结果。</td>
</tr>
<tr>
<td>JB-MasterSign（三选一）</td>
<td>将masterKey加上":"再加上timestamp组成的字符串，再对它做 MD5 签名后的结果。</td>
</tr>
<tr>
<td>JB-Sign（三选一）</td>
<td>将key加上":"再加上timestamp组成的字符串，再对它做 MD5 签名后的结果。</td>
</tr>
</tbody>
</table>
<p>其中<code>JB-AdminSign</code> <code>JB-MasterSign</code> <code>JB-Sign</code>为三选一。使用<code>JB-AdminSign</code>时为超级授权、使用<code>JB-MasterSign</code>时为管理授权、使用<code>JB-Sign</code>时为普通授权。使用管理授权或普通授权时为了指定被操作的App，因此必须有<code>JB-AppId</code>。</p>
<p>加密计算实现（Java）：</p>
<pre><code class="java">public String encrypt(String key, String timeStamp) {
        return md5(key + &quot;:&quot; + timeStamp);
    }
</code></pre>

<p>其中<code>key</code>在不同的授权下、分别可以是<code>key</code> <code>masterKey</code> <code>adminKey</code>，<code>JB-timeStamp</code>为当前系统时间戳。返回结果为请求header中所需的<code>JB-Sign</code>或<code>JB-MasterSign</code>或<code>JB-AdminSign</code>。使用管理授权或普通授权时必须有<code>JB-AppId</code></p>
<h2 id="_4">响应格式</h2>
<p>对于所有的请求的响应格式都是一个 JSON 对象.</p>
<p>一个请求是否成功是由 HTTP 状态码标明的。一个 200 的状态码表示成功，而一个 400 表示请求失败。当一个请求失败时响应的主体仍然是一个 JSON 对象，但是总是会包含<code>code</code>和<code>error</code>这两个字段，你可以用它们来进行调试。</p>
<h2 id="_5">接口概览</h2>
<p>每个接口都有其调用所需要的对应权限。无权限或使用错误的权限将调用失败。</p>
<h3 id="_6">应用（超级权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/admin/app</td>
<td>POST</td>
<td>创建应用</td>
</tr>
<tr>
<td>/admin/app/{appId}</td>
<td>GET</td>
<td>获取应用</td>
</tr>
<tr>
<td>/admin/app</td>
<td>GET</td>
<td>列表</td>
</tr>
<tr>
<td>/admin/app/{appId}</td>
<td>DELETE</td>
<td>删除应用</td>
</tr>
</tbody>
</table>
<h3 id="_7">类（管理权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/master/clazz</td>
<td>POST</td>
<td>创建类</td>
</tr>
<tr>
<td>/master/clazz/{className}</td>
<td>GET</td>
<td>获取类</td>
</tr>
<tr>
<td>/master/clazz</td>
<td>GET</td>
<td>列表</td>
</tr>
<tr>
<td>/master/clazz/{className}</td>
<td>DELETE</td>
<td>删除类</td>
</tr>
</tbody>
</table>
<h3 id="_8">字段（管理权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/master/clazz/{className}/field</td>
<td>POST</td>
<td>创建字段</td>
</tr>
<tr>
<td>/master/clazz/{className}/field/{fieldName}</td>
<td>GET</td>
<td>获取字段</td>
</tr>
<tr>
<td>/master/clazz/{className}/field/{fieldName}</td>
<td>PUT</td>
<td>更新字段</td>
</tr>
<tr>
<td>/master/clazz/{className}/field</td>
<td>GET</td>
<td>字段列表</td>
</tr>
<tr>
<td>/master/clazz/{className}/field/{fieldName}</td>
<td>DELETE</td>
<td>删除字段</td>
</tr>
</tbody>
</table>
<h3 id="_9">对象（管理权限 普通权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/object/{className}</td>
<td>POST</td>
<td>创建对象</td>
</tr>
<tr>
<td>/object/{className}/{id}</td>
<td>GET</td>
<td>获取对象</td>
</tr>
<tr>
<td>/object/{className}/{id}</td>
<td>PUT</td>
<td>更新对象</td>
</tr>
<tr>
<td>/object/{className}</td>
<td>GET</td>
<td>查询对象</td>
</tr>
<tr>
<td>/object/{className}/{id}</td>
<td>DELETE</td>
<td>删除对象</td>
</tr>
</tbody>
</table>
<h3 id="_10">用户（管理权限 普通权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/user</td>
<td>POST</td>
<td>注册用户</td>
</tr>
<tr>
<td>/user/{id}</td>
<td>PUT</td>
<td>修改用户信息</td>
</tr>
<tr>
<td>/user/login</td>
<td>GET</td>
<td>用户登录</td>
</tr>
</tbody>
</table>
<h3 id="_11">设备（管理权限 普通权限）</h3>
<table>
<thead>
<tr>
<th>URL</th>
<th>METHOD</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>/installation</td>
<td>POST</td>
<td>注册设备</td>
</tr>
</tbody>
</table>
<h2 id="_12">用户</h2>
<p>用户系统是所有应用中最常见的子系统，为了避免重复建设，提高开发效率，<code>JavaBaas</code>内建了简单的用户系统。</p>
<p>用户类<code>User</code>的基本功能与其他的类是相同的。用户对象和其他对象不同的是，每个用户必须有用户名<code>username</code>和密码<code>password</code>，密码会被自动地加密和存储。JavaBaas强制要求<code>username</code>和<code>email</code>这两个字段必须是没有重复的。</p>
<h3 id="_13">注册</h3>
<p>注册一个新用户与创建一个新的普通对象之间的不同点在于<code>username</code>和<code>password</code>字段都是必需的。<code>password</code>字段会以和其他的字段不一样的方式处理，它在储存时会被加密而且永远不会被返回给任何来自客户端的请求。</p>
<p>为了注册一个新的用户，需要向<code>user</code>路径发送一个POST请求，且可以在创建时同时提交一个自定义字段。例如，创建一个有昵称的新用户（其中昵称为自定义字段）:</p>
<pre><code>curl -X POST \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;username&quot;:&quot;codi&quot;,&quot;password&quot;:&quot;123456&quot;,&quot;nickname&quot;:&quot;Codi&quot;}' \
    (host)/users
</code></pre>

<p>当创建成功时，会返回新创建的用户信息。
包含<code>_id</code> <code>createdAt</code> <code>sessionToken</code>等信息：</p>
<pre><code>{
  &quot;code&quot;: 0,
  &quot;data&quot;: {
    &quot;_id&quot;: &quot;1c4978776f924fd48bd86905e21dd828&quot;,
    &quot;createdAt&quot;: 1444962473797,
    &quot;sessionToken&quot;: &quot;2040f95a9a634e02aa9ae1e8bf6a0ea0&quot;
  },
  &quot;message&quot;: &quot;&quot;
}
</code></pre>

<h3 id="_14">登录</h3>
<p>用户注册成功后，可以使用用户名密码进行登录，登录成功后，会获得所有的用户信息。</p>
<pre><code>curl -X GET \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -G \
  --data-urlencode 'username=codi' \
  --data-urlencode 'password=123456' \
    (host)/user/login
</code></pre>

<p>其中：</p>
<ul>
<li>username:用户名</li>
<li>password:密码</li>
</ul>
<p>返回用户信息。</p>
<pre><code>{
  &quot;_id&quot;: &quot;1c4978776f924fd48bd86905e21dd828&quot;,
  &quot;createdAt&quot;: 1444962051055,
  &quot;updatedAt&quot;: 1444962051055,
  &quot;acl&quot;: {
    &quot;*&quot;: {
      &quot;read&quot;: true,
      &quot;write&quot;: true
    }
  },
  &quot;sessionToken&quot;: &quot;2040f95a9a634e02aa9ae1e8bf6a0ea0&quot;,
  &quot;username&quot;: &quot;codi&quot;,
  &quot;nickname&quot;: &quot;Codi&quot;
}
</code></pre>

<h3 id="sessiontoken">SessionToken</h3>
<p>在<code>JavaBaas</code>中，所有的请求通过添加请求头<code>JB-SessionToken</code>来表示当前请求的用户身份。因此，在注册或登录成功后，客户端需缓存用户的<code>SessionToken</code>作为之后请求的身份标识。同时，当用户密码信息变化时，之前获取的<code>SessionToken</code>将失效，需重新登录进行获取。</p>
<h3 id="_15">修改密码</h3>
<p>修改密码需要让用户输入一次旧密码做验证，旧密码正确才可以修改为新密码。同时，登录用户才可以修改自己的密码，因此调用修改密码接口需要在请求头中加入<code>JB-SessionToken</code>来表示当前请求的用户身份。</p>
<pre><code>curl -X PUT \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;JB-SessionToken:(sign)&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;oldPassword&quot;:&quot;123456&quot;,&quot;newPassword&quot;:&quot;654321&quot;}' \
    (host)/{id}/updatePassword
</code></pre>

<p>其中：</p>
<ul>
<li>id:用户id</li>
<li>old_password:用户的老密码</li>
<li>new_password:用户的新密码</li>
</ul>
<h3 id="_16">绑定第三方平台</h3>
<p><code>JavaBaas</code>支持将系统用户与第三方平台用户进行绑定。如新浪微博、微信、qq等，这样就允许你的用户直接用第三方平台用户身份进行登录。关联完成后，authData将被存储到用户信息中，并通过登录即可重新获取。</p>
<p>首先使用第三方平台进行用户授权（或使用ShareSdk等工具），完成授权后第三方平台讲返回accessToken以及用户id等信息。客户端向<code>JavaBaas</code>提交此信息后，后台会进行授权检查，检查通过后完成绑定。</p>
<pre><code>curl -X POST \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;JB-SessionToken:(sessionToken)&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;accessToken&quot;:&quot;69B307BA98F8C8D2455CC8D9040A6A96&quot;,&quot;uid&quot;:&quot;AB782D5190C50B588B536145FEEF6A0F&quot;}' \
    (host)/{id}/binding/{platform}
</code></pre>

<p>其中：</p>
<ul>
<li>id:用户id</li>
<li>platform:第三方平台的名称，微博:weibo、qq:qq、微信:weixin。</li>
<li>accessToken:使用第三方平台授权时获取的token</li>
<li>uid:使用第三方平台授权时获取的用户身份表示，其中微博取uid字段，qq、微信取openId字段</li>
</ul>
<h3 id="_17">解绑第三方平台</h3>
<p>使用此接口将用户与第三方平台解除绑定。</p>
<pre><code>curl -X DELETE \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;JB-SessionToken:(sessionToken)&quot; \
  -H &quot;Content-Type: application/json&quot; \
    (host)/{id}/release/{platform}
</code></pre>

<p>其中：</p>
<ul>
<li>id:用户id</li>
<li>platform:第三方平台的名称，微博:weibo、qq:qq、微信:weixin。</li>
</ul>
<h3 id="_18">使用第三方平台登录</h3>
<p>用户于第三方平台绑定后，可以使用第三方平台授权信息进行登录操作。登录成功后，会获得所有的用户信息。</p>
<pre><code>curl -X POST \
  -H &quot;JB-Timestamp:(timestamp)&quot; \
  -H &quot;JB-AppId:(appId)&quot; \
  -H &quot;JB-Sign:(sign)&quot; \
  -H &quot;Content-Type: application/json&quot; \
  -d '{&quot;accessToken&quot;:&quot;69B307BA98F8C8D2455CC8D9040A6A96&quot;,&quot;uid&quot;:&quot;AB782D5190C50B588B536145FEEF6A0F&quot;}'
    (host)/user/loginWithSns/{platform}
</code></pre>

<p>其中：</p>
<ul>
<li>platform:第三方平台的名称，微博:weibo、qq:qq、微信:weixin。</li>
<li>accessToken:使用第三方平台授权时获取的token</li>
<li>uid:使用第三方平台授权时获取的用户身份表示，其中微博取uid字段，qq、微信取openId字段</li>
</ul>
<p>返回用户信息。</p>
<pre><code>{
  &quot;_id&quot;: &quot;1c4978776f924fd48bd86905e21dd828&quot;,
  &quot;createdAt&quot;: 1444962051055,
  &quot;updatedAt&quot;: 1444962051055,
  &quot;acl&quot;: {
    &quot;*&quot;: {
      &quot;read&quot;: true,
      &quot;write&quot;: true
    }
  },
  &quot;sessionToken&quot;: &quot;2040f95a9a634e02aa9ae1e8bf6a0ea0&quot;,
  &quot;username&quot;: &quot;codi&quot;,
  &quot;nickname&quot;: &quot;Codi&quot;
}
</code></pre></div>
            
        </div>

        <footer class="col-md-12">
            <hr>
            
            <p>Documentation built with <a href="http://www.mkdocs.org/">MkDocs</a>.</p>
        </footer>

        <script src="../js/jquery-1.10.2.min.js"></script>
        <script src="../js/bootstrap-3.0.3.min.js"></script>
        <script src="../js/highlight.pack.js"></script>
        <script>var base_url = '..';</script>
        <script data-main="../mkdocs/js/search.js" src="../mkdocs/js/require.js"></script>
        <script src="../js/base.js"></script>

        <div class="modal" id="mkdocs_search_modal" tabindex="-1" role="dialog" aria-labelledby="Search Modal" aria-hidden="true">
            <div class="modal-dialog">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">Close</span></button>
                        <h4 class="modal-title" id="exampleModalLabel">Search</h4>
                    </div>
                    <div class="modal-body">
                        <p>
                            From here you can search these documents. Enter
                            your search terms below.
                        </p>
                        <form role="form">
                            <div class="form-group">
                                <input type="text" class="form-control" placeholder="Search..." id="mkdocs-search-query">
                            </div>
                        </form>
                        <div id="mkdocs-search-results"></div>
                    </div>
                    <div class="modal-footer">
                    </div>
                </div>
            </div>
        </div>

    </body>
</html>
